const db = wx.cloud.database();
const _ = db.command; // 新增：引入数据库操作符
const GreenHouseCollection = db.collection('Greenhouse_Data');
const wxCharts = require('../../libs/wxcharts-min'); // 确保路径正确

Page({
  data: {
    selectedData: null, // 存储大棚详细数据
    detectedData: [], // 图表数据
    userMessageContent: '', // 云函数入参
    useMsg: '', // 云函数返回结果
    loading: true,
    sortedData: [], // 存储最近6小时的数据
    timeLabels: [], // 横坐标时间标签（如5:00-10:00）
    videoUrl: '', 
    videoStatus: 'idle',
    videoError: '',
    logs: [],
    nextVideoUrl: '',
    isLoadingNext: false,
    // 音频相关状态（已修复重复定义问题）
    cancelRequest: false,   // 是否取消语音请求
    audioPlaying: false,    // 是否正在播放音频
    tempPcmPath: '',        // 临时PCM文件路径
    tempWavPath: '',         // 临时WAV文件路径
    AIloading: false, // 新增：控制语音合成加载状态
  },
  
  // 初始化视频进度监听
  initVideoWatcher() {
    const videoContext = wx.createVideoContext('greenhouseVideo');
    
    // 监听视频播放进度
    videoContext.onTimeUpdate(() => {
      const { duration, currentTime } = videoContext;
      // 当视频剩余时间小于3秒且未开始加载下一个视频时
      if (duration - currentTime <= 3 && !this.data.isLoadingNext) {
        this.setData({ isLoadingNext: true });
        this.preloadNextVideo();
      }
    });
  },

  // 预加载下一个视频
  preloadNextVideo() {
    console.log('开始预加载下一个视频...');
    this.getLatestVideoUrl().then(url => {
      this.setData({ nextVideoUrl: url });
      console.log('下一个视频预加载完成');
    }).catch(err => {
      console.error('预加载失败:', err);
      this.setData({ isLoadingNext: false });
    });
  },

  // 视频播放结束时，立即切换到预加载的视频
  handleVideoEnded() {
    console.log('视频播放结束，切换到下一个视频');
    if (this.data.nextVideoUrl) {
      this.setData({ 
        videoUrl: this.data.nextVideoUrl,
        nextVideoUrl: '',
        isLoadingNext: false
      });
    } else {
      // 如果预加载失败，重新获取
      this.getLatestVideoUrl();
    }
  },
  // 新增：获取视频URL
  async getLatestVideoUrl() {
    this.updateLog('开始获取最新视频URL');
    this.setData({ videoStatus: 'loading' });
    
    try {
      const res = await new Promise((resolve, reject) => {
        wx.request({
          url: 'http://82.157.209.238:8080/get_latest_video',
          method: 'GET',
          success: (res) => {
            if (res.data.status === 'success') {
              this.updateLog(`成功获取视频URL: ${res.data.video_url.substring(0, 50)}...`);
              resolve(res.data.video_url);
            } else {
              this.updateLog(`获取视频失败: ${res.data.msg}`, 'error');
              reject(new Error('获取视频失败：' + res.data.msg));
            }
          },
          fail: (err) => {
            this.updateLog(`网络请求失败: ${err.errMsg}`, 'error');
            reject(new Error('网络请求失败：' + err.errMsg));
          }
        });
      });
      
      this.setData({ 
        videoUrl: res,
        videoStatus: 'playing',
        videoError: ''
      });
      
    } catch (error) {
      this.setData({ 
        videoStatus: 'error',
        videoError: error.message
      });
    }
  },

  // 新增：更新日志
  updateLog(message, level = 'info') {
    const timestamp = new Date().toLocaleTimeString();
    const logEntry = {
      timestamp,
      level,
      message
    };
    
    const logs = [...this.data.logs, logEntry];
    // 限制日志数量，避免占用过多内存
    if (logs.length > 20) logs.shift();
    
    this.setData({ logs });
    console[level](`[${timestamp}] ${message}`);
  },

  /**
   * 页面加载时获取大棚 ID 并查询数据
   */
  onLoad(options) {
    const greenhouseId = options.greenhouseId;
    this.fetchRecent6HoursData(greenhouseId); // 改为获取最近6小时数据
    this.getLatestVideoUrl(); // 新增：获取视频
    this.initVideoWatcher();
    // 初始化音频上下文（全局唯一，减少内存占用）
    this.initAudioContext();
  },

/**
 * 从数据库获取最近6小时的数据（带详细调试日志）
 */
async fetchRecent6HoursData(greenhouseId) {
  console.log('======== fetchRecent6HoursData 开始 ========');
  console.log('请求的大棚ID:', greenhouseId);
  
  try {
    // 1. 计算时间范围（使用本地时间，与数据库存储的+08:00时间匹配）
    const now = new Date();
    const sixHoursAgo = new Date(now.getTime() - 6 * 60 * 60 * 1000);
    
    console.log('本地当前时间:', now.toLocaleString());
    console.log('本地6小时前时间:', sixHoursAgo.toLocaleString());
    
    // 2. 生成数据库查询时间（确保格式与数据库存储一致）
    const formatToISO = (date) => {
      const offset = date.getTimezoneOffset();
      const offsetHours = Math.abs(Math.floor(offset / 60));
      const offsetMinutes = Math.abs(offset % 60);
      const offsetSign = offset <= 0 ? '+' : '-';
      
      return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}T${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}:${date.getSeconds().toString().padStart(2, '0')}${offsetSign}${offsetHours.toString().padStart(2, '0')}:${offsetMinutes.toString().padStart(2, '0')}`;
    };
    
    const queryStart = formatToISO(sixHoursAgo);
    const queryEnd = formatToISO(now);

    console.log('查询时间范围:', queryStart, '至', queryEnd);

    // 3. 修正数据库查询条件（使用and组合条件，避免覆盖）
    console.log('开始数据库查询...');
    const startTime = Date.now();
    
    const res = await GreenHouseCollection
      .where({
        greenhouseID: greenhouseId,
        // 关键修复：使用and组合两个条件，确保时间范围有效
        monitortime: db.command.and(
          db.command.gte(queryStart),
          db.command.lte(queryEnd)
        )
      })
      .orderBy('monitortime', 'asc')
      .get();

    const queryTime = Date.now() - startTime;
    console.log(`数据库查询完成，耗时 ${queryTime}ms`);
    console.log('查询到的数据量:', res.data.length);
    
    // 检查是否有数据返回
    if (res.data.length === 0) {
      console.warn('未查询到最近6小时内的数据');
      wx.showToast({ title: '暂无最近6小时数据', icon: 'none' });
      // this.setData({ loading: false });
      return;
    }
    
    // 打印查询到的时间样本
    console.log('查询到的数据时间样本:');
    const sampleCount = Math.min(3, res.data.length);
    for (let i = 0; i < sampleCount; i++) {
      console.log(`  ${i+1}. ${res.data[i].monitortime}`);
    }
    if (res.data.length > 3) {
      console.log(`  ...等共 ${res.data.length} 条数据`);
    }

    // 4. 处理数据
    let recentData = res.data;
    
    // 验证并转换时间格式
    recentData = recentData.map(item => {
      try {
        const parsedTime = new Date(item.monitortime);
        return {
          ...item,
          parsedTime: parsedTime,
          isValidTime: !isNaN(parsedTime.getTime())
        };
      } catch (e) {
        console.error('时间解析失败:', item.monitortime, e);
        return { ...item, parsedTime: new Date(0), isValidTime: false };
      }
    });
    
    // 过滤无效时间数据
    const invalidCount = recentData.filter(item => !item.isValidTime).length;
    if (invalidCount > 0) {
      console.warn(`发现 ${invalidCount} 条数据时间格式无效，已过滤`);
      recentData = recentData.filter(item => item.isValidTime);
    }
    
    // 按时间排序（确保升序）
    recentData.sort((a, b) => a.parsedTime - b.parsedTime);
    
    // 再次过滤超出时间范围的数据（双重保险）
    const originalCount = recentData.length;
    recentData = recentData.filter(item => 
      item.parsedTime >= sixHoursAgo && item.parsedTime <= now
    );
    const filteredCount = originalCount - recentData.length;
    if (filteredCount > 0) {
      console.log(`二次过滤掉 ${filteredCount} 条超出时间范围的数据`);
    }
    
    // 验证最终时间范围
    if (recentData.length > 0) {
      const firstTime = recentData[0].parsedTime;
      const lastTime = recentData[recentData.length - 1].parsedTime;
      console.log('有效数据时间范围:', 
        firstTime.toLocaleString(), '至', 
        lastTime.toLocaleString()
      );
    } else {
      console.warn('所有数据均超出时间范围');
      wx.showToast({ title: '暂无有效数据', icon: 'none' });
      // this.setData({ loading: false });
      return;
    }
    
    // 截取最近6条（如果数据量超过6条）
    if (recentData.length > 6) {
      const removedCount = recentData.length - 6;
      recentData = recentData.slice(-6);
      console.log(`截取最近6条数据，移除了 ${removedCount} 条较早数据`);
    }

    // 5. 生成时间标签（精确到小时和分钟）
    const timeLabels = recentData.map(item => {
      const hour = item.parsedTime.getHours().toString().padStart(2, '0');
      const minute = item.parsedTime.getMinutes().toString().padStart(2, '0');
      return `${hour}:${minute}`;
    });
    console.log('最终用于图表的时间标签:', timeLabels.join(' -> '));

    // 6. 获取最新数据
    const selectedData = recentData[recentData.length - 1];
    console.log('最新数据时间:', selectedData.monitortime);
    console.log('最新数据值:', {
      temperature: selectedData.temperature,
      humidity: selectedData.humidity,
      light: selectedData.light,
      'gas(CO2)': selectedData['gas(CO2)']
    });

    // 7. 处理图表归一化数据
    const detectedData = [
      Math.min(1.0, selectedData.temperature / 32).toFixed(2),
      Math.min(1.0, selectedData.humidity / 80).toFixed(2),
      Math.min(1.0, selectedData.light / 10000).toFixed(2),
      Math.min(1.0, selectedData['gas(CO2)'] / 1500).toFixed(2)
    ];

    // 8. 构建云函数入参
    const userMessageContent = `我的葡萄种植大棚现在的温度是${selectedData.temperature}℃,湿度是${selectedData.humidity}%,光照强度是${selectedData.light}勒克斯,二氧化碳浓度是${selectedData['gas(CO2)']}ppm，我需要做什么措施吗？打开通风扇，打开棚顶，打开日光灯，抽水还是什么都不要做？请用段落式来回答，不要使用markdown格式,由于你的输出是字符串，在我这里成像是没有顺序的，因此请在需要换行的地方加上\n\n,然后每段首行也要缩进两个空，也用相应的字符表示`;

    this.setData({
      selectedData,
      detectedData,
      userMessageContent,
      sortedData: recentData,
      timeLabels,
      // loading: false
    }, () => {
      console.log('数据已更新到页面状态');
      this.drawChart();
      console.log('图表绘制完成');
      this.callCloudFunction(); // 确保有数据时调用云函数
    });

    console.log('======== fetchRecent6HoursData 结束 ========');

  } catch (e) {
    console.error('获取最近6小时数据失败:', e);
    wx.showToast({ title: '数据加载失败', icon: 'none' });
    // this.setData({ loading: false });
  }
},

  /**
   * 绘制图表（核心修改：使用动态时间标签）
   */
  drawChart() {
    const { sortedData, timeLabels, detectedData } = this.data;
    if (sortedData.length === 0) return;

    // 1. 柱状图（保持不变）
    new wxCharts({
      canvasId: 'barCanvas',
      type: 'column',
      categories: ['温度', '湿度', '光照强度', 'CO2浓度'],
      series: [
        { name: '检测值', data: detectedData, color: '#FF6B6B' },
        { name: '正常值', data: [1, 1, 1, 1], color: '#4ECDC4' }
      ],
      dataLabel: false,
      yAxis: { title: '归一化值', min: 0 },
      width: 350,
      height: 200,
      animation: true,
      background: '#FFF'
    });

    // 2. 温度曲线（横坐标使用动态时间标签）
    new wxCharts({
      canvasId: 'lineCanvas_tem',
      type: 'line',
      categories: timeLabels, // 动态时间标签（如5:00-10:00）
      series: [{ 
        name: '温度(℃)', 
        data: sortedData.map(item => item.temperature.toFixed(1)), 
        color: '#FF6B6B',
        dataLabel: true
      }],
      dataLabel: true,
      yAxis: { title: '温度(℃)', min: Math.min(...sortedData.map(item => item.temperature)) - 2 }, // 自适应最小值
      width: 350,
      height: 200,
      animation: true,
      background: '#FFF',
      lineWidth: 2,
      pointSize: 5,
      smooth: true,
    });

    // 3. 湿度曲线
    new wxCharts({
      canvasId: 'lineCanvas_hum',
      type: 'line',
      categories: timeLabels, // 动态时间标签
      series: [{ 
        name: '湿度(%)', 
        data: sortedData.map(item => item.humidity.toFixed(1)), 
        color: '#4ECDC4',
        dataLabel: true
      }],
      dataLabel: true,
      yAxis: { title: '湿度(%)', min: Math.min(...sortedData.map(item => item.humidity)) - 5 },
      width: 350,
      height: 200,
      animation: true,
      background: '#FFF',
      lineWidth: 2,
      pointSize: 5,
      smooth: true,
    });

    // 4. 光照强度曲线
    new wxCharts({
      canvasId: 'lineCanvas_light',
      type: 'line',
      categories: timeLabels, // 动态时间标签
      series: [{ 
        name: '光照(勒克斯)', 
        data: sortedData.map(item => item.light.toFixed(1)), 
        color: '#FFD166',
        dataLabel: true
      }],
      dataLabel: true,
      yAxis: { title: '光照强度(勒克斯)', min: 0 },
      width: 350,
      height: 200,
      animation: true,
      background: '#FFF',
      lineWidth: 2,
      pointSize: 5,
      smooth: true,
    });

    // 5. CO2浓度曲线
    new wxCharts({
      canvasId: 'lineCanvas_CO2',
      type: 'line',
      categories: timeLabels, // 动态时间标签
      series: [{ 
        name: 'CO2(ppm)', 
        data: sortedData.map(item => item['gas(CO2)'].toFixed(1)), 
        color: '#06D6A0',
        dataLabel: true
      }],
      dataLabel: true,
      yAxis: { title: '二氧化碳浓度(ppm)', min: Math.min(...sortedData.map(item => item['gas(CO2)'])) - 100 },
      width: 350,
      height: 200,
      animation: true,
      background: '#FFF',
      lineWidth: 2,
      pointSize: 5,
      smooth: true,
    });
  },

  /**
   * 调用云函数
   */
  callCloudFunction() {
    const { userMessageContent } = this.data;
    wx.cloud.callFunction({
      name: 'BlueLM-70BAPI',
      data: { prompt: userMessageContent },
      success: res => {
        console.log('云函数调用成功', res.result);
        this.setData({ useMsg: res.result.data ,loading:false});
      },
      fail: err => {
        console.error('云函数调用失败', err);
        wx.showToast({ title: '获取建议失败', icon: 'none' });
      }
    });
  },
  // 音频播放
   /**
   * 初始化音频上下文（复用逻辑，避免重复创建）
   */
  initAudioContext() {
    if (!this.audioCtx) {
      this.audioCtx = wx.createInnerAudioContext();
      // 监听音频自然结束
      this.audioCtx.onEnded(() => {
        this.setData({ audioPlaying: false });
        this.cleanupAudio(); // 播放结束后清理资源
      });
      // 监听手动停止
      this.audioCtx.onStop(() => {
        this.setData({ audioPlaying: false });
        this.cleanupAudio();
      });
      // 监听播放错误
      this.audioCtx.onError((err) => {
        console.error('音频播放失败:', err);
        wx.showToast({ title: '播放失败', icon: 'none' });
        this.setData({ audioPlaying: false });
        this.cleanupAudio();
      });
    }
  },

  /**
   * 点击语音图标，调用服务器合成音频并播放
   */
  synthesizeSpeech() {
    const text = this.data.useMsg;
    // 文本为空校验
    if (!text.trim()) {
      wx.showToast({ title: '暂无AI建议内容', icon: 'none' });
      return;
    }
    // 文本长度限制（防止音频过大）
    const MAX_TEXT_LENGTH = 500;
    if (text.length > MAX_TEXT_LENGTH) {
      wx.showToast({
        title: `文本过长（超过${MAX_TEXT_LENGTH}字）`,
        icon: 'none'
      });
      return;
    }
    // 防止重复请求
    if (this.data.AIloading) return;

    this.setData({ 
      AIloading: true, 
      cancelRequest: false,
      audioPlaying: false 
    });

    // 保存请求任务，支持取消
    this.speechRequestTask = wx.request({
      url: 'http://82.157.209.238:5000/api/tts', // 已改为HTTPS（必须）
      method: 'POST',
      data: { text: text },
      header: { 'Content-Type': 'application/json' },
      timeout: 60000, // 超时时间60秒
      success: (res) => {
        if (this.data.cancelRequest) return; // 已取消则不处理

        if (res.data.success) {
          // 成功获取音频，调用播放方法
          this.playAudio(res.data.audio_base64);
        } else {
          wx.showToast({
            title: res.data.error || '语音合成失败',
            icon: 'none'
          });
        }
      },
      fail: (err) => {
        if (this.data.cancelRequest) return;

        console.error('语音合成接口调用失败:', err);
        // 细化错误提示
        let errorMsg = '网络请求失败';
        if (err.errMsg.includes('timeout')) {
          errorMsg = '合成超时，请稍后重试';
        } else if (err.errMsg.includes('ssl') || err.errMsg.includes('http')) {
          errorMsg = '请使用HTTPS协议';
        }
        wx.showToast({ title: errorMsg, icon: 'none' });
      },
      complete: () => {
        if (!this.data.cancelRequest) {
          this.setData({ AIloading: false });
        }
      }
    });
  },

  /**
   * 取消语音合成请求
   */
  cancelSynthesis() {
    if (this.data.AIloading && this.speechRequestTask) {
      this.speechRequestTask.abort(); // 终止请求
      this.setData({ 
        AIloading: false, 
        cancelRequest: true,
        audioPlaying: false 
      });
      wx.showToast({ title: '已取消合成', icon: 'none' });
    }
  },

  /**
 * 播放音频（处理Base64格式音频）
 */
playAudio(base64Data) {
  // 新增：检查并初始化音频上下文（防止未初始化或被意外重置）
  if (!this.audioCtx) {
    this.initAudioContext();
    console.warn('音频上下文未初始化，已自动创建');
  }

  // 移除Base64前缀（兼容可能带前缀的音频数据）
  const pureBase64 = base64Data.replace(/^data:audio\/\w+;base64,/, '');
  if (!pureBase64) {
    wx.showToast({ title: '音频数据格式错误', icon: 'none' });
    return;
  }

  // 转换为ArrayBuffer（小程序要求的二进制格式）
  try {
    var buffer = wx.base64ToArrayBuffer(pureBase64);
  } catch (err) {
    console.error('Base64转ArrayBuffer失败:', err);
    wx.showToast({ title: '音频解码失败', icon: 'none' });
    this.cleanupAudio();
    return;
  }

  // 生成临时文件路径（使用时间戳确保唯一性，避免文件冲突）
  const timestamp = Date.now();
  const tempPcmPath = `${wx.env.USER_DATA_PATH}/tts_${timestamp}.pcm`;
  const tempWavPath = `${wx.env.USER_DATA_PATH}/tts_${timestamp}.wav`;
  this.setData({ tempPcmPath, tempWavPath });

  // 写入PCM文件到本地临时目录
  const fs = wx.getFileSystemManager();
  fs.writeFile({
    filePath: tempPcmPath,
    data: buffer,
    encoding: 'binary', // 必须指定为binary，否则写入格式错误
    success: () => {
      // 核心修复：使用箭头函数作为回调，确保this指向页面实例
      this.convertPcmToWav(tempPcmPath, tempWavPath, () => {
        // 再次校验audioCtx（双重保险）
        if (!this.audioCtx) {
          console.error('音频上下文丢失，播放失败');
          wx.showToast({ title: '播放失败', icon: 'none' });
          this.cleanupAudio();
          return;
        }

        // 设置音频源并播放
        this.audioCtx.src = tempWavPath;
        this.audioCtx.play();
        this.setData({ audioPlaying: true }); // 标记播放状态
        console.log('音频开始播放，临时路径:', tempWavPath);
      });
    },
    fail: (err) => {
      console.error('PCM文件写入失败:', err);
      wx.showToast({ title: '音频文件处理失败', icon: 'none' });
      this.cleanupAudio(); // 失败时清理临时文件
    }
  });
},

  /**
   * 停止当前播放
   */
  stopAudio() {
    if (this.audioCtx && this.data.audioPlaying) {
      this.audioCtx.stop();
      this.setData({ audioPlaying: false });
    }
  },

  /**
   * PCM转WAV（优化数据复制效率）
   */
  convertPcmToWav(pcmPath, wavPath, callback) {
    const fs = wx.getFileSystemManager();
    fs.readFile({
      filePath: pcmPath,
      success: (res) => {
        const pcmData = res.data;
        const sampleRate = 24000; // 与服务器采样率一致
        const bitDepth = 16; // 16位采样
        const numChannels = 1; // 单声道

        // 构建WAV文件头（44字节）
        const buffer = new ArrayBuffer(44 + pcmData.byteLength);
        const view = new DataView(buffer);

        // RIFF chunk
        view.setUint8(0, 0x52); // 'R'
        view.setUint8(1, 0x49); // 'I'
        view.setUint8(2, 0x46); // 'F'
        view.setUint8(3, 0x46); // 'F'
        view.setUint32(4, 36 + pcmData.byteLength, true);
        view.setUint8(8, 0x57); // 'W'
        view.setUint8(9, 0x41); // 'A'
        view.setUint8(10, 0x56); // 'V'
        view.setUint8(11, 0x45); // 'E'

        // fmt subchunk
        view.setUint8(12, 0x66); // 'f'
        view.setUint8(13, 0x6d); // 'm'
        view.setUint8(14, 0x74); // 't'
        view.setUint8(15, 0x20); // ' '
        view.setUint32(16, 16, true); // PCM格式
        view.setUint16(20, 1, true); // 线性PCM
        view.setUint16(22, numChannels, true);
        view.setUint32(24, sampleRate, true);
        view.setUint32(28, sampleRate * numChannels * (bitDepth / 8), true);
        view.setUint16(32, numChannels * (bitDepth / 8), true);
        view.setUint16(34, bitDepth, true);

        // data subchunk
        view.setUint8(36, 0x64); // 'd'
        view.setUint8(37, 0x61); // 'a'
        view.setUint8(38, 0x74); // 't'
        view.setUint8(39, 0x61); // 'a'
        view.setUint32(40, pcmData.byteLength, true);

        // 优化：批量复制PCM数据（替代for循环）
        const pcmView = new Uint8Array(pcmData);
        const wavView = new Uint8Array(buffer);
        wavView.set(pcmView, 44); // 从第44字节开始写入

        // 写入WAV文件
        fs.writeFile({
          filePath: wavPath,
          data: buffer,
          encoding: 'binary',
          success: callback,
          fail: (err) => {
            console.error('WAV文件转换失败:', err);
            wx.showToast({ title: '音频格式转换失败', icon: 'none' });
            this.cleanupAudio(); // 失败时清理
          }
        });
      },
      fail: (err) => {
        console.error('读取PCM文件失败:', err);
        this.cleanupAudio(); // 失败时清理
      }
    });
  },

  /**
   * 清理音频资源（删除临时文件+重置状态）
   */
  cleanupAudio() {
    const { tempPcmPath, tempWavPath } = this.data;
    const fs = wx.getFileSystemManager();

    // 尝试删除临时文件（忽略删除失败的错误）
    if (tempPcmPath) {
      try { fs.unlinkSync(tempPcmPath); } catch (e) { /* 忽略错误 */ }
    }
    if (tempWavPath) {
      try { fs.unlinkSync(tempWavPath); } catch (e) { /* 忽略错误 */ }
    }

    // 重置临时文件路径
    this.setData({
      tempPcmPath: '',
      tempWavPath: ''
    });
  },
  onUnload() {
    // 销毁音频上下文，释放资源
    if (this.audioCtx) {
      this.audioCtx.destroy();
      this.audioCtx = null;
    }
    // 确保临时文件被删除
    this.cleanupAudio();
  }
});